﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Caixa.DAO;
using Caixa.Model;

namespace Caixa.BLL
{
	public static class ContaBLL
	{
		#region " Methods "

		#region " Get Methods "

		public static Conta GetByID(int id)
		{
			return ContaDAO.GetByID(id);
		}

		public static Conta GetByNumero(int numero)
		{
			return ContaDAO.GetByNumero(numero);
		}

		public static bool ValidaAcesso(int conta, string senha)
		{
			bool success = false;

			//Resgata a conta pelo número
			Conta c = ContaDAO.GetByNumero(conta);
			if (c == null)
				throw new Exception("Número de conta inválido.");

			//Valida se a senha é válida
			success = (c != null && c.Senha.Equals(senha));
			if (!success)
				throw new Exception("Senha inválida.");

			return success;
		}

		#endregion

		#region " Management Methods "

		public static bool Saque(Conta c, double valor)
		{
			bool success = false;

			//Verifica se conta está ativa
			if (!c.Ativo)
				throw new Exception("Conta inativa! O saque não pode ser feito pois essa conta está inativa.");

			//Verifica se o valor para saque é maior que zero
			if (valor <= 0)
				throw new Exception("Valor inválido! Valor para saque deve ser maior que 0(zero).");

			//Verifica se a conta possui saldo para este saque
			if (c.Saldo < valor)
				throw new Exception("Saldo insuficiente! O saque não pode ser feito pois o saldo da conta é inferior ao valor do saque.");

			//Insere a movimentação referente ao saque, a qual já irá atualizar o saldo da conta
			success = InserirMovimentacao(c.ID, Movimentacao.TipoMovimentacao.Debito, "Saque", valor);

			//Atualiza as informações da conta (mais especificamente o saldo)
			c = ContaBLL.GetByID(c.ID);

			//Se o saque zerar o saldo da conta, a conta se torna inativa
			if (success && c.Saldo.Equals(0))
			{
				c.Ativo = false;
				success = ContaBLL.Update(c);
			}

			return success;
		}

		public static bool Deposito(Conta c, double valor)
		{
			bool success = false;

			//Verifica se o valor para depósito é maior que zero
			if (valor <= 0)
				throw new Exception("Valor inválido! Valor para depósito deve ser maior que 0(zero).");

			//Insere a movimentação referente ao depósito, a qual já irá atualizar o saldo da conta
			success = InserirMovimentacao(c.ID, Movimentacao.TipoMovimentacao.Credito, "Depósito", valor);

			//Atualiza as informações da conta (mais especificamente o saldo)
			c = ContaBLL.GetByID(c.ID);

			//Se a conta estiver inativa e o depósito deixar o 
			//saldo da conta maior que zero, a conta se torna ativa
			if (success && (!c.Ativo) && (c.Saldo > 0))
			{
				c.Ativo = true;
				success = ContaBLL.Update(c);
			}

			return success;
		}

		private static bool InserirMovimentacaoInicial(Conta c)
		{
			return InserirMovimentacao(c.ID, Movimentacao.TipoMovimentacao.Credito, "Saldo Inicial", c.Saldo);
		}

		private static bool InserirMovimentacao(int contaID, Movimentacao.TipoMovimentacao tipo, string descricao, double valor)
		{
			return InserirMovimentacao(contaID, tipo, DateTime.Now, descricao, valor);
		}

		private static bool InserirMovimentacao(int contaID, Movimentacao.TipoMovimentacao tipo, DateTime data, string descricao, double valor)
		{
			Movimentacao m = new Movimentacao();
			m.IDConta = contaID;
			m.Tipo = tipo;
			m.Data = data;
			m.Descricao = descricao;
			m.Valor = valor;

			return (MovimentacaoBLL.Insert(m) > 0);
		}

		#endregion

		#region " DDL Methods "

		public static int Insert(Conta c)
		{
			//Verifica se a conta possui saldo maior que zero
			if (c.Saldo <= 0)
				throw new Exception("O saldo da conta deve ser maior que 0(zero)!");

			//Verifica se o cadastro do cliente da conta existe
			if (!ClienteBLL.ExisteCliente(c.IDCliente))
				throw new Exception("O cliente desta conta é inválido!");

			//Insere a conta
			c.ID = ContaDAO.Insert(c);

			//Se a conta foi inserida com sucesso,insere uma 
			//movimentação referente ao saldo inicial da conta
			if (c.ID > 0)
			{
				InserirMovimentacaoInicial(c);
			}

			return c.ID;
		}

		public static bool Update(Conta c)
		{
			return ContaDAO.Update(c);
		}

		public static bool Delete(Conta c)
		{
			return ContaDAO.Delete(c);
		}

		#endregion

		#endregion
	}
}
